﻿#region zh-CHS 2006 - 2008 DemoSoft 团队 | en 2006 - 2008 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the MMOSE(Massively Multiplayer Online Server Engine) for .NET.
//
//                              2006-2008 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using Demo.Mmose.Core.Common;
using Demo.Mmose.Core.Util;
#endregion

namespace Demo.Mmose.Misc.Net.Dll
{
    /// <summary>
    /// 客户段的主处理
    /// </summary>
    [MultiThreadedSupport( "zh-CHS", "当前的类所有成员都可锁定,支持多线程操作" )]
    public class SocketClient
    {
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 客户段的主处理指针
        /// </summary>
        private IntPtr m_SocketClient                                   = IntPtr.Zero;
        /// <summary>
        /// 客户段的主处理管理句柄
        /// </summary>
        private ConnectHandleManager m_ConnectHandleManager             = new ConnectHandleManager();

        /// <summary>
        /// 处理数据的回调函数
        /// </summary>
        private DelegateProcessMessageBlock m_ProcessMessageBlock       = null;
        /// <summary>
        /// 处理断开的回调函数
        /// </summary>
        private DelegateDisconnect m_Disconnect                         = null;
        #endregion

        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 初始化构造
        /// </summary>
        public SocketClient()
        {
            m_ProcessMessageBlock   = new DelegateProcessMessageBlock(this.OnProcessMessageBlock);
            m_Disconnect            = new DelegateDisconnect(this.OnDisconnect);
        }
        #endregion

        #region zh-CHS 共有属性 | en Public Properties
        /// <summary>
        /// 客户端是够已经连接
        /// </summary>
        public bool IsConnected
        {
            get { return SocketClient.SocketClient_IsConnected( m_SocketClient ); }
        }

        /// <summary>
        /// 客户端的管理句柄
        /// </summary>
        public ConnectHandleManager ConnectHandleManager
        {
            get { return m_ConnectHandleManager; }
        }
        #endregion

        #region zh-CHS 共有方法 | en Public Methods
        /// <summary>
        /// 开始连接服务端
        /// </summary>
        /// <param name="strHostNamePort"></param>
        public bool StartConnectServer( string strHostNamePort )
        {
            if ( m_SocketClient != IntPtr.Zero )
            {
                Debug.WriteLine( "SocketClient.StartConnectServer(...) - m_SocketClient != IntPtr.Zero error!" );
                return false;
            }

            if ( SocketClient.SocketClient_StartConnectServer( strHostNamePort, m_ProcessMessageBlock, m_Disconnect, ref m_SocketClient ) == false )
            {
                Debug.WriteLine( "SocketClient.StartConnectServer(...) - SocketClient.SocketClient_StartConnectServer(...) == false error!" );
                return false;
            }

            IntPtr socketHandlerManagerAtClient = IntPtr.Zero;
            if ( SocketClient.SocketClient_GetConnectHandlerManager( ref socketHandlerManagerAtClient, m_SocketClient ) == false )
            {
                Debug.WriteLine( "SocketClient.StartConnectServer(...) - SocketClient.SocketClient_GetSocketHandlerManager(...) == false error!" );
                return false;
            }

            if ( socketHandlerManagerAtClient == IntPtr.Zero )
            {
                Debug.WriteLine( "SocketClient.StartConnectServer(...) - socketHandlerManagerAtClient == IntPtr.Zero error!" );
                return false;
            }

            m_ConnectHandleManager.Value = socketHandlerManagerAtClient;
            return true;
        }

        /// <summary>
        /// 发送数据到服务端
        /// </summary>
        /// <param name="byteBuffer"></param>
        /// <param name="iLength"></param>
        public void SendBuffer( byte[] byteBuffer, int iLength )
        {
            MessageBlock messageBlock  = m_ConnectHandleManager.GetNewSendMessageBlock();
            if ( messageBlock == null )
            {
                Debug.WriteLine( "SocketClient.SendBuffer(...) - messageBlock == null error!" );
                return;
            }

            Marshal.Copy( byteBuffer, 0, messageBlock.WritePointer(), iLength );
            messageBlock.WritePointer( iLength );

            SocketClient.SocketClient_SendBuffer( messageBlock.Value, m_SocketClient );
        }

        /// <summary>
        /// 发送数据到服务端
        /// </summary>
        /// <param name="byteBuffer"></param>
        /// <param name="iLength"></param>
        public void SendBuffer( MessageBlock messageBlock )
        {
            SocketClient.SocketClient_SendBuffer( messageBlock.Value, m_SocketClient );
        }

        /// <summary>
        /// 停止连接
        /// </summary>
        public void StopConnect()
        {
            if ( m_SocketClient == IntPtr.Zero )
                return;

            SocketClient.SocketClient_StopConnect( m_SocketClient );

            m_SocketClient = IntPtr.Zero;
        }
        #endregion

        #region zh-CHS 共有事件 | en Public Event
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<ProcessMessageBlockAtClientEventArgs> m_EventProcessMessageBlock;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockEventProcessMessageBlock = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 处理数据时的事件
        /// </summary>
        public event EventHandler<ProcessMessageBlockAtClientEventArgs> EventProcessMessageBlock
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockEventProcessMessageBlock );
                {
                    m_EventProcessMessageBlock += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockEventProcessMessageBlock );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockEventProcessMessageBlock );
                {
                    m_EventProcessMessageBlock -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockEventProcessMessageBlock );
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private EventHandler<DisconnectAtClientEventArgs> m_EventDisconnect;
        /// <summary>
        /// 
        /// </summary>
        private ReaderWriterLockSlim m_LockEventDisconnect = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 处理断开时的事件
        /// </summary>
        public event EventHandler<DisconnectAtClientEventArgs> EventDisconnect
        {
            add
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockEventDisconnect );
                {
                    m_EventDisconnect += value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockEventDisconnect );
            }
            remove
            {
                ReaderWriterLockSlimEx.EnterWriteLock( m_LockEventDisconnect );
                {
                    m_EventDisconnect -= value;
                }
                ReaderWriterLockSlimEx.ExitWriteLock( m_LockEventDisconnect );
            }
        }
        #endregion

        #region zh-CHS 私有委托 | en Private Delegate
        /// <summary>
        /// 处理数据的委托
        /// </summary>
        /// <param name="pRecvMessageBlock"></param>
        /// <param name="pNonceClientHandler"></param>
        /// <param name="pHandlerManager"></param>
        private delegate void DelegateProcessMessageBlock(IntPtr pRecvMessageBlock, IntPtr pNonceClientHandler, IntPtr pHandlerManager);
        /// <summary>
        /// 处理断开的委托
        /// </summary>
        /// <param name="pNonceClientHandler"></param>
        /// <param name="pHandlerManager"></param>
        private delegate void DelegateDisconnect(IntPtr pNonceClientHandler, IntPtr pHandlerManager);
        #endregion

        #region zh-CHS 私有的事件处理函数 | en Private Event Handlers
        /// <summary>
        /// 处理数据
        /// </summary>
        /// <param name="pRecvMessageBlock"></param>
        /// <param name="pNonceClientHandler"></param>
        /// <param name="pAllHandlerManager"></param>
        private void OnProcessMessageBlock(IntPtr pRecvMessageBlock, IntPtr pNonceClientHandler, IntPtr pAllHandlerManager)
        {
            EventHandler<ProcessMessageBlockAtClientEventArgs> tempEvent = m_EventProcessMessageBlock;
            if ( m_EventProcessMessageBlock != null )
            {
                MessageBlock recvMessageBlock = new MessageBlock();
                if (recvMessageBlock == null)
                {
                    Debug.WriteLine( "SocketClient.OnProcessMessageBlock(...) - recvMessageBlock == null error!" );
                    
                    return;
                }
                recvMessageBlock.Value = pRecvMessageBlock;

                ConnectHandle nonceClientHandler = new ConnectHandle();
                if (nonceClientHandler == null)
                {
                    Debug.WriteLine( "SocketClient.OnProcessMessageBlock(...) - nonceClientHandler == null error!" );

                    return;
                }
                nonceClientHandler.Value = pNonceClientHandler;

                ConnectHandleManager allHandlerManager = new ConnectHandleManager();
                if (allHandlerManager == null)
                {
                    Debug.WriteLine( "SocketClient.OnProcessMessageBlock(...) - allHandlerManager == null error!" );
                    
                    return;
                }
                allHandlerManager.Value = pAllHandlerManager;
                nonceClientHandler.SocketHandlerManager = allHandlerManager;

                ProcessMessageBlockAtClientEventArgs processEventArgs = new ProcessMessageBlockAtClientEventArgs( recvMessageBlock, nonceClientHandler, allHandlerManager );
                tempEvent( this, processEventArgs );
            }
        }

        /// <summary>
        /// 处理断开
        /// </summary>
        /// <param name="pNonceClientHandler"></param>
        /// <param name="pAllHandlerManager"></param>
        private void OnDisconnect(IntPtr pNonceClientHandler, IntPtr pAllHandlerManager)
        {
            EventHandler<DisconnectAtClientEventArgs> tempEvent = m_EventDisconnect;
            if ( tempEvent != null )
            {
                ConnectHandle nonceClientHandler = new ConnectHandle();
                if (nonceClientHandler == null)
                {
                    Debug.WriteLine( "SocketClient.OnProcessMessageBlock(...) - nonceClientHandler == null error!" );
                    
                    return;
                }
                nonceClientHandler.Value = pNonceClientHandler;

                ConnectHandleManager allHandlerManager = new ConnectHandleManager();
                if (allHandlerManager == null)
                {
                    Debug.WriteLine( "SocketClient.OnProcessMessageBlock(...) - allHandlerManager == null error!" );
                    
                    return;
                }
                allHandlerManager.Value = pAllHandlerManager;

                DisconnectAtClientEventArgs disconnectEventArgs = new DisconnectAtClientEventArgs( nonceClientHandler, allHandlerManager );
                tempEvent( this, disconnectEventArgs );
            }
        }
        #endregion

        #region zh-CHS 引入DLL接口 | en DLL Import
        /// <summary>
        /// dll 调用
        /// </summary>
        /// <param name="strHostNamePort"></param>
        /// <param name="DelegateProcessMessageBlock"></param>
        /// <param name="DelegateDisconnect"></param>
        /// <param name="pSocketMainServer"></param>
        /// <returns></returns>
        [DllImport( "Demo.Mmose.Net.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode )]
        private static extern bool SocketClient_StartConnectServer( string strHostNamePort, DelegateProcessMessageBlock DelegateProcessMessageBlock, DelegateDisconnect DelegateDisconnect, ref IntPtr pSocketMainServer );

        /// <summary>
        /// dll 调用
        /// </summary>
        /// <param name="pSocketMainServer"></param>
        [DllImport("Demo.Mmose.Net.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern void SocketClient_StopConnect( IntPtr pSocketMainServer );

        /// <summary>
        /// dll 调用
        /// </summary>
        /// <param name="pSocketMainServer"></param>
        /// <returns></returns>
        [DllImport("Demo.Mmose.Net.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern bool SocketClient_IsConnected( IntPtr pSocketMainServer );

        /// <summary>
        /// dll 调用
        /// </summary>
        /// <param name="pBuffer"></param>
        /// <param name="iLength"></param>
        /// <param name="pSocketMainServer"></param>
        /// <returns></returns>
        [DllImport("Demo.Mmose.Net.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern bool SocketClient_SendBuffer( IntPtr pMessageBlock, IntPtr pSocketMainServer );

        /// <summary>
        /// dll 调用
        /// </summary>
        /// <param name="pSocketHandlerManagerAtClient"></param>
        /// <param name="pSocketMainServer"></param>
        /// <returns></returns>
        [DllImport("Demo.Mmose.Net.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern bool SocketClient_GetConnectHandlerManager( ref IntPtr pSocketHandlerManagerAtClient, IntPtr pSocketMainServer );
        #endregion
    }
}
#endregion

